java中有三种遍历集合的方式:
System.out.println("----------method1-----------");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println("----------method2-----------");
for (String s : list) {
System.out.println(s);
//ConcurrentModificationException,其实JAVA中的增强for循环底层是通过迭代器模式来实现的。
//list.remove(s);
}
System.out.println("----------method3-----------");
Iterator iterator=list.iterator();
while(iterator.hasNext()){
String s= (String) iterator.next();
if(s.equals("value1")){
//安全删除
iterator.remove();
}else{
System.out.println(s);
}
}
运行方法2的时候,如果调用list.foreach方法,会报ConcurrentModificationException异常,
对以下代码反编译:
for (Integer i : list) {
System.out.println(i);
}
编译后的结果:
Integer i;
for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println(i)){
i = (Integer)iterator.next();
}
可以看到foreach的实现其实是用了迭代器,利用迭代器在集合遍历是删除会报ConcurrentModificationException异常,所以需要使用迭代器自带的删除方法操作,如果遍历时候需要删除操作,使用第三种(method3)遍历方式。
Iterator是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出java.util.ConcurrentModificationException异常。
所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象,Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。